import logging
import time

from PySide6.QtCore import Signal, QPointF, QRectF, QSizeF
from PySide6.QtGui import Qt, QPen
from PySide6.QtWidgets import QGraphicsWidget, QGraphicsSceneMouseEvent, QSizePolicy

from . import 最小宽度, 最小高度, 网格大小, 边框厚度, 节点初始背景颜色, 节点初始边框颜色
from ...节点管理器.动态数据调度器.属性管理器 import 属性管理基类

# 配置日志记录器
logging.basicConfig(level=logging.WARNING, format='%(asctime)s - %(levelname)s - %(message)s')
日志记录器 = logging.getLogger(__name__)

class 节点基础图形项(QGraphicsWidget):
    节点检查节点大小信号 = Signal()
    节点位置更新信号 = Signal()

    def __init__(self,节点模型,父容器节点图形项管理器, 父项=None):
        super().__init__(父项)
        self.调试模式 = False  # 调试模式开关
        # 设置日志等级
        if self.调试模式:
            日志记录器.setLevel(logging.DEBUG)
            日志记录器.debug(f"{self.__class__.__name__}调试模式已开启")
        else:
            日志记录器.setLevel(logging.ERROR)  # 只显示警告及以上级别的日志

        日志记录器.info("创建节点基础图形项")
        self.父容器节点图形项管理器 = 父容器节点图形项管理器
        self.属性管理器 = 属性管理基类()
        self.属性管理器.属性同步对象=节点模型

        self.边框颜色 = None
        if 父项:
            self.setParentItem(父项)
        self.父项 = 父项
        self.正在调整节点大小 = False
        self.能否手动调整节点大小 = True
        self.左键状态 = False
        self.最小宽度 = 最小宽度
        self.最小高度 = 最小高度
        self.边框厚度 = 边框厚度
        self.背景颜色 = 节点初始背景颜色
        self.边框颜色 = 节点初始边框颜色
        self.可移动 = True
        self.可选择 = True

        self.节点检查节点大小信号.connect(self.计算节点最小边界)
        self.注册属性变动触发函数("节点位置", self.更新节点位置)
        self.节点位置更新信号.connect(self.更新节点位置)
        self.图形项属性 = self.属性管理器.属性
        self._初始化节点()
        日志记录器.info("完成初始化节点基础图形项")
        self._上次日志的时间 = 0  # 初始化上次日志的时间
        self._日志输出间隔 = 2 # 日志输出间隔，单位为秒
        #self._接口图形项集合 = set()
    def 设置属性(self, 属性名, 属性值):
        self.属性管理器.设置属性(属性名, 属性值)
    def 获取属性值(self, 属性名):
        return self.属性管理器.获取属性值(属性名)
    def 注册属性变动触发函数(self, 属性名, 触发函数):
        self.属性管理器.注册属性触发函数(属性名, 触发函数)
    def 设置属性触发函数(self, 属性名, 触发函数):
        self.属性管理器.设置属性触发函数(属性名, 触发函数)
    def 注销属性触发函数(self, 属性名, 触发函数):
        self.属性管理器.注销属性触发函数(属性名, 触发函数)
    def _初始化节点(self):
        # 设置大小策略，允许调整节点大小
        self.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Expanding)

        # 设置移动和选择标志
        flags = QGraphicsWidget.GraphicsItemFlags()
        if self.可移动:
            flags |= QGraphicsWidget.ItemIsMovable
        if self.可选择:
            flags |= QGraphicsWidget.ItemIsSelectable
        self.setFlags(flags)

        self.setAcceptHoverEvents(True)  # 接受悬停事件
    def 获取属性(self, 属性名):
        return self.属性管理器.获取属性值(属性名)

    def 计算节点最小边界(self):
        子项边界 = self.childrenBoundingRect()
        子项最小空间 = 子项边界.size()
        self.最小宽度 = 子项最小空间.width()
        self.最小高度 = 子项最小空间.height()

    def 判断是否在边框(self, pos: QPointF) -> bool:
        rect = self.rect()
        return (rect.right() - self.边框厚度 <= pos.x() <= rect.right() and
                rect.bottom() - self.边框厚度 <= pos.y() <= rect.bottom())

    def hoverMoveEvent(self, event: QGraphicsSceneMouseEvent):
        """ 鼠标悬停事件 """
        self.设置边框颜色(Qt.blue)  # 鼠标悬停时改变边框颜色
        if self.能否手动调整节点大小:
            if self.判断是否在边框(event.pos()):
                self.setCursor(Qt.SizeFDiagCursor)
        super().hoverMoveEvent(event)

    def hoverLeaveEvent(self, event: QGraphicsSceneMouseEvent):
        """ 鼠标离开事件 """
        self.设置边框颜色(self.边框颜色)  # 恢复为默认边框颜色
        self.setCursor(Qt.ArrowCursor)  # 恢复为默认箭头光标
        super().hoverLeaveEvent(event)

    def mousePressEvent(self, event: QGraphicsSceneMouseEvent):
        """ 鼠标按下事件 """
        if event.button() == Qt.LeftButton:# 左键按下
            self.左键状态 = True
            if self.能否手动调整节点大小:
                if self.判断是否在边框(event.pos()):
                    self.正在调整节点大小 = True
                else:
                    self.正在调整节点大小 = False
        super().mousePressEvent(event)

    def mouseReleaseEvent(self, event: QGraphicsSceneMouseEvent):
        """ 鼠标松开事件 """
        if event.button() == Qt.LeftButton:# 左键松开
            日志记录器.info("基础图形项 左键鼠标松开")
            self.左键状态 = False
            self.正在调整节点大小 = False
        super().mouseReleaseEvent(event)
        self.吸附到网格(self.pos())

    def mouseMoveEvent(self, event: QGraphicsSceneMouseEvent):
        """ 鼠标移动事件 """
        调整过节点大小=False
        if self.左键状态 and self.正在调整节点大小:
            当前鼠标位置 = event.scenePos()
            局部鼠标位置 = self.mapFromScene(当前鼠标位置)
            self.设置节点大小(QSizeF(局部鼠标位置.x(), 局部鼠标位置.y()))
            调整过节点大小=True
        elif self.左键状态:
            # if 起始接口.图形项属性.get("所属节点模型管理器").容器:
            if self.父容器节点图形项管理器.容器:
                new_pos = self.pos() + event.pos() - event.lastPos()
                self.setPos(new_pos)
                self.父容器节点图形项管理器.容器.容器内容改变信号.emit()
            elif self.父容器节点图形项管理器.场景:
                new_pos = self.pos() + event.pos() - event.lastPos()
                self.setPos(new_pos)
            # else:
            #     super().mouseMoveEvent(event)
        else:
            super().mouseMoveEvent(event)
        if 调整过节点大小:
            当前时间 = time.time()  # 获取当前时间
            if 当前时间 - self._上次日志的时间 > self._日志输出间隔:  # 判断时间间隔
                日志记录器.info("基础图形项 正在调整节点大小")
                self._上次日志的时间 = 当前时间  # 更新上次日志时间
        self.刷新接口()

    def paint(self, painter, option, widget=None):
        pen = QPen(Qt.NoPen)
        if hasattr(self, '当前画笔'):
            pen = self.当前画笔
        else:
            pen = QPen(self.边框颜色, 1)
        painter.setPen(pen)
        painter.setBrush(self.背景颜色)
        painter.drawRoundedRect(self.boundingRect(), 10, 10)

    def 设置边框颜色(self,颜色=None, width=2):
        if not 颜色:
            颜色 = self.边框颜色
        self.当前画笔 = QPen(颜色, width)
        self.update()

    def 设置节点大小(self, 节点大小):
        self.prepareGeometryChange()
        self.setGeometry(QRectF(self.geometry().topLeft(), 节点大小))
        self.updateGeometry()
        self.update()

    def 更新节点位置(self, 位置=None):
        #print("更新节点位置")

        if 位置 is None:
            位置 = self.获取属性('节点位置')
        #print(位置)
        if isinstance(位置, list):
            位置 = QPointF(位置[0], 位置[1])
        self.吸附到网格(位置)

    def 吸附到网格(self, 位置: QPointF):
        x = round(位置.x() / 网格大小) * 网格大小
        y = round(位置.y() / 网格大小) * 网格大小
        if self.父项:
            if x < 0: x = 0
            if y < 0: y = 0
        self.prepareGeometryChange()
        self.setPos(QPointF(x, y))
        if self.父容器节点图形项管理器.容器:
            self.父容器节点图形项管理器.容器.容器内容改变信号.emit()
        self.刷新接口()

    def 删除当前图形项(self):
        if self.父项:
            self.setParentItem(None)
        if self.scene():
            self.scene().removeItem(self)
        self.deleteLater()

    def itemChange(self, change, value):
        self.刷新接口()
        return super().itemChange(change, value)

    def 刷新接口(self):
        raise NotImplementedError("请在子类中实现刷新接口函数")

